home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48_1 / appr.sho < prev    next >
Text File  |  1995-03-23  |  14KB  |  620 lines

  1. Article 1670 of comp.sys.handhelds:
  2. From: madler@tybalt.caltech.edu (Mark Adler)
  3. Newsgroups: comp.sys.handhelds
  4. Subject: Shorter APPT, APDIR (this is a LONG message)
  5. Date: 29 Mar 90 20:13:24 GMT
  6. Organization: California Institute of Technology, Pasadena
  7.  
  8. After getting the Appointment application (APPT and APDIR) from the
  9. HP bulletin board and kermiting it over to my calculator, I found
  10. that I didn't have much memory left.  With a few other things loaded
  11. in as well (the stopwatch, some of my own things), I started thinking
  12. about buying more memory for the thing.  Then I looked at the
  13. programs in APDIR, and decided it was really a ploy to make me get
  14. more memory.  It almost worked too!
  15.  
  16. Without changing the functionality whatsoever, I reduced the size of
  17. APDIR from 13714 bytes to 8173.5 bytes.  I did this by rewriting
  18. parts of the programs, putting them all in one directory, and
  19. combining some programs (and even fixing a bug or two here and
  20. there).  It is even a little faster now.  The thing really deserves a
  21. total rewrite, and I estimate it could be made faster and more
  22. functional in less than 5 or 6K bytes.  But, alas, I don't have time
  23. for that. Anyway, here is the shortened version, first APPT and then
  24. APDIR.
  25.  
  26. Mark Adler
  27. madler@tybalt.caltech.edu
  28.  
  29. %%HP: T(3)A(R)F(.);
  30. @ Store as 'APPT'
  31. @ 'APPT' BYTES should give CRC #5470h, and length 83.5.
  32. \<<
  33.   APDIR
  34.   RCLF 'flags' STO MYFLGS STOF
  35.   CNTL
  36.   flags STOF HOME 2 MENU
  37. \>>
  38.  
  39. %%HP: T(3)A(R)F(.);
  40. @ Store as 'APDIR'
  41. @ 'APDIR' BYTES should give CRC #B8C7h, and length 8173.5.
  42. @ Note that if APPT is run, APDIR changes.
  43.  
  44. DIR
  45.  
  46. CNTL
  47. @ Main function---called by APPT (not in APDIR)
  48. @ Setup and process keystrokes at top (calendar) level.
  49. \<<
  50.   DEPTH \->LIST 'STACK' STO             @ save stack
  51.   DATE 'DSTR' STO                       @ set date to current date
  52.   REFRESH                               @ put up calendar
  53.   DO                                    @ process keys until ...
  54.     -1 WAIT DOKEY
  55.   UNTIL
  56.     IP 16 ==                            @  menu key F.
  57.   END
  58.   DROP2 STACK OBJ\-> DROP               @ restore stack
  59. \>>
  60.  
  61.  
  62. REFRESH
  63. @ called by CNTL, DOKEY (5)
  64. @ Put up calendar display and menu.
  65. \<<
  66.   @ SETUP
  67.   { "FIND" "GOTO" "ADD" "UPLD" "APPTS" "Stop" } MENU DSTR SETUP2
  68.   MNTH LCD\->
  69.   @ HLIT
  70.   Dy ADR + 7 / FP 7 * 3 * 6 * 1 - 'COL' STO
  71.   Dy ADR + 7 / IP 1 + 8 * 1 - 'ROW' STO
  72.   DUP COL R\->B ROW R\->B 2 \->LIST COL 12 + R\->B ROW 8 + R\->B
  73.   2 \->LIST SUB NEG COL R\->B ROW R\->B 2 \->LIST SWAP REPL
  74.   DUP \->LCD
  75. \>>
  76.  
  77.  
  78. DOKEY
  79. @ called by CNTL
  80. @ Execute the keystroke on the stack for the calendar menu, update DSTR.
  81. \<<
  82.   { 11.1 { DROP SRCMAIN REFRESH 11.1 }
  83.     12.1 { DROP GOTO REFRESH 12.1 }
  84.     13.1 { CLEAR DSTR TIME 100 * IP 100 / "" 0 4 \->LIST
  85.            BEG 1 CF REFRESH 13.1 }
  86.     14.1 { DROP OVERALL REFRESH 14.1 }
  87.     15.1 { APPTS REFRESH 15.1 }
  88.     36.1 DYPL 34.1 DYMIN 35.1 NWEEK 25.1 PWEEK
  89.     95.1 MOPL 85.1 MOMIN 95.2 YRPLS 85.2 YRMIN
  90.     91.3 OFF
  91.   }
  92.   DUP2 SWAP POS
  93.   IF DUP THEN
  94.     1 + GET EVAL
  95.   ELSE
  96.     DROP2
  97.   END
  98.   Yr OBJ\-> 10000 / Dy + 100 / Mo + 'DSTR' STO
  99. \>>
  100.  
  101.  
  102. SRCMAIN
  103. @ called by DOKEY
  104. @ FIND key: find an appointment and go to that date.
  105. \<<
  106.   @ GTSTR
  107.   DROP2 { } MENU "Type search string\010Then press ENTER."  SRCSTR
  108.   \Ga 2 \->LIST INPUT 'SRCSTR' STO
  109.   CLLCD "Searching" 2 DISP
  110.   @ GTALN
  111.   DSTR FINDALARM 'NXTALRM' STO
  112.   @ SRCALRM
  113.   0 'ENDALRM' STO 0 'FNDALRM' STO
  114.   DO
  115.     NXTALRM
  116.     IFERR RCLALARM THEN
  117.       1 'ENDALRM' STO
  118.     ELSE
  119.       @ CHKALRM
  120.       1 GETI TIME TSTR 1 12 SUB 4 DISP DROP 3 GETI SWAP DROP
  121.       DUP TYPE 2 ==
  122.       IF THEN
  123.         SRCSTR POS
  124.       ELSE
  125.         DROP 0
  126.       END
  127.       IF THEN
  128.         1 'FNDALRM' STO
  129.       ELSE
  130.         DROP
  131.       END
  132.     END
  133.     NXTALRM 1 + 'NXTALRM' STO
  134.   UNTIL
  135.     ENDALRM FNDALRM OR
  136.   END
  137.   @ ENDPROC
  138.   IF ENDALRM THEN
  139.     CLEAR CLLCD "No appointment found\010\010Press a top row key." 3 DISP
  140.     -1 WAIT DROP
  141.   ELSE
  142.     1 GET 'DSTR' STO
  143.   END
  144. \>>
  145.  
  146.  
  147. GOTO
  148. @ called by DOKEY
  149. @ GOTO key: goto the entered date.
  150. \<<
  151.   DROP2 { } MENU "Type date (MM.DDYYYY):\010Then press ENTER."
  152.   DSTR \->STR -1 2 \->LIST INPUT OBJ\-> 'DSTR' STO
  153. \>>
  154.  
  155.  
  156. YRMIN
  157. @ called by DOKEY
  158. @ left - key: go back one year.
  159. \<<
  160.   ROT DROP2 DSTR .000001 - RDOSCR
  161. \>>
  162.  
  163. YRPLS
  164. @ called by DOKEY
  165. @ left + key: go forward one year.
  166. \<<
  167.   ROT DROP2 DSTR .000001 + RDOSCR
  168. \>>
  169.  
  170. MOMIN
  171. @ called by DOKEY
  172. @ - key: go back one month.
  173. \<<
  174.   ROT DROP2 DSTR DUP IP 1 - SWAP 100 * FP 100 / .01 + + DUP
  175.   IF 1 < THEN
  176.     .000001 - 12 +
  177.   END
  178.   RDOSCR
  179. \>>
  180.  
  181. MOPL
  182. @ called by DOKEY
  183. @ + key: go forward one month.
  184. \<<
  185.   ROT DROP2 DSTR DUP IP 1 + SWAP 100 * FP 100 / .01 + + DUP
  186.   IF 13 > THEN FP
  187.     1.000001 +
  188.   END
  189.   RDOSCR
  190. \>>
  191.  
  192. PWEEK
  193. @ called by DOKEY
  194. @ down key: go forward one week (but stay in month).
  195. \<<
  196.   IF Dy 7 > THEN
  197.     SWAP HLIT2 Dy 7 - 'Dy' STO RC HLIT2 DUP \->LCD SWAP
  198.   ELSE
  199.     400 .2 BEEP
  200.   END
  201. \>>
  202.  
  203. NWEEK
  204. @ called by DOKEY
  205. @ up key: go back one week (but stay in month).
  206. \<<
  207.   IF Dy DSTR LMNTH 6 - < THEN
  208.     SWAP HLIT2 7 Dy + 'Dy' STO RC HLIT2 DUP \->LCD SWAP
  209.   ELSE
  210.     400 .2 BEEP
  211.   END
  212. \>>
  213.  
  214. DYMIN
  215. @ called by DOKEY
  216. @ left key: go back one day (but stay in month).
  217. \<<
  218.   IF Dy 1 > THEN
  219.     SWAP HLIT2 Dy 1 - 'Dy' STO RC HLIT2 DUP \->LCD SWAP
  220.   ELSE
  221.     400 .2 BEEP
  222.   END
  223. \>>
  224.  
  225. DYPL
  226. @ called by DOKEY
  227. @ right key: go forward one day (but stay in month).
  228. \<<
  229.   IF Dy DSTR LMNTH < THEN
  230.     SWAP HLIT2 1 Dy + 'Dy' STO RC HLIT2 DUP \->LCD SWAP
  231.   ELSE
  232.     400 .2 BEEP
  233.   END
  234. \>>
  235.  
  236.  
  237. OVERALL
  238. @ called by DOKEY
  239. @ UPLD key: dump a range of appointments to I/O device.
  240. \<<
  241.   @ GDATES
  242.   "Enter Start Date\010(MM.DDYYYY)\010Then press ENTER" DSTR
  243.   \->STR -1 2 \->LIST INPUT OBJ\-> 'SDAT' STO
  244.   "Enter End Date\010(MM.DDYYYY)\010Then press ENTER" DSTR
  245.   \->STR -1 2 \->LIST INPUT OBJ\-> 'ENDAT' STO
  246.   "\010"
  247.   @ RAPPTS
  248.   SDAT FINDALARM DUP 'NXTALRM' STO
  249.   SDAT DFLIP 'SDAT' STO
  250.   ENDAT DFLIP 'ENDAT' STO
  251.   CLLCD
  252.   "Finding appointments" 1 DISP
  253.   WHILE
  254.     @ GDALRM
  255.     IFERR RCLALARM THEN
  256.       DROP 0
  257.     ELSE
  258.       DUP 1 GET DFLIP DUP SDAT \>= SWAP ENDAT \<= AND
  259.       IF THEN
  260.         1
  261.       ELSE
  262.         DROP 0
  263.       END
  264.     END
  265.   REPEAT
  266.     @ MKSTR
  267.     DUP 1 GETI 3 ROLLD GET TSTR 1 19 SUB "  " + SWAP 3 GET DUP
  268.     IF TYPE 2 == THEN
  269.       +
  270.     ELSE
  271.       DROP "Control Alarm" +
  272.     END
  273.     + "\010" + NXTALRM 1 + DUP 'NXTALRM' STO
  274.   END
  275.   'APPTSTR' STO
  276.   @ TOPC
  277.   CLLCD
  278.   "The data is ready.\010Press the appropriate\010key when you are\010ready."
  279.   1 DISP { "SEND" "" "" "" "" "ABRT" } MENU
  280.   DO
  281.     -1 WAIT
  282.     IF DUP 11.1 == THEN
  283.       DROP 'APPTSTR'
  284.       IFERR CLLCD SEND THEN
  285.         DROP CLLCD
  286.         "I/O Problem\010Check configuration\010and retry." 1 DISP
  287.       ELSE
  288.         CLLCD "Successful transfer" 1 DISP
  289.       END
  290.       3 WAIT 16.1
  291.     END
  292.   UNTIL
  293.     16.1 ==
  294.   END
  295.   CLEAR
  296. \>>
  297.  
  298. DFLIP
  299. @ called by OVERALL (3)
  300. @ Change MM.DDYYYY to YYYYMMDD for numerical comparisons.
  301. \<<
  302.   100 * DUP IP SWAP FP 100000000 * +
  303. \>>
  304.  
  305.  
  306. APPTS
  307. @ called by DOKEY
  308. @ APPTS key: show appointments for selected day, allow operations.
  309. \<<
  310.   3 DROPN
  311.   IF
  312.     @ FAPPTS
  313.     DSTR FINDALARM DUP
  314.     IF THEN
  315.       @ ALRM\->
  316.       'NXTALRM' STO
  317.       DO
  318.         NXTALRM
  319.         IFERR RCLALARM THEN
  320.           DROP DSTR 1 + 1 \->LIST
  321.         ELSE
  322.           OBJ\-> DROP NXTALRM 5 \->LIST NXTALRM 1 + 'NXTALRM' STO
  323.         END
  324.       UNTIL
  325.         DUP 1 GET DSTR \=/
  326.       END
  327.       DROP
  328.     ELSE
  329.       DROP
  330.     END
  331.     DEPTH
  332.   THEN
  333.     DEPTH ROLL
  334.     @ APS\->MS
  335.     DEPTH 1 SWAP
  336.     START
  337.       @ OAL\->MSG
  338.       DUP 5 GET SWAP DUP 3 GET SWAP 2 GET DUP IP DUP
  339.       IF 10 < THEN
  340.         "0" SWAP +
  341.       END
  342.       ":" + SWAP FP 100 * IP DUP
  343.       IF NOT THEN
  344.         DROP "00"
  345.       END
  346.       + " " + SWAP + SWAP 2 \->LIST
  347.       DEPTH ROLL
  348.     NEXT
  349.     @ PSTMSG
  350.     PG
  351.     DO
  352.       -1 WAIT
  353.       @ DOK5 and DOKX
  354.       { 91.3 OFF
  355.         25.1 { DROP DEPTH ROLL PG 25.1 }
  356.         35.1 { DROP DEPTH ROLLD PG 35.1 }
  357.         11.1 \<<
  358.           DROP 2 GETI SWAP DROP DUP RCLALARM SWAP DELALARM DUP BEG
  359.           IF 1 FC? THEN
  360.             STOALARM
  361.           ELSE
  362.             DROP
  363.           END
  364.           1 CF 16.1
  365.         \>>
  366.         12.1 { DROP 2 GETI SWAP DROP
  367.           # 18CEAh SYSEVAL # E402h SYSEVAL # 3244h SYSEVAL
  368.           # E80Dh SYSEVAL # 172Bh SYSEVAL DROP2 12.1 }
  369.         13.1 { DROP 2 GET DELALARM 16.1 }
  370.         14.1 { DROP DSTR TIME 100 * IP 100 / "" 0 4 \->LIST BEG 1 CF 16.1 }
  371.         15.1 \<<
  372.           DROP
  373.           @ PRVW
  374.           CLLCD DUP 1 GET DUP SIZE 7 SWAP SUB DUP SIZE 1 SWAP
  375.           FOR x
  376.             DUP 1 22 SUB x 22 / 1 + DISP
  377.             IF DUP SIZE 22 > THEN
  378.               DUP SIZE 23 SWAP SUB
  379.             END
  380.           22 STEP
  381.           DROP { "" "" "" "" "" "RTRN" } MENU -1 WAIT DROP
  382.           PG 15.1
  383.         \>>
  384.       }
  385.       IF DEPTH 7 > THEN
  386.         { 25.2 { DROP 1 5 START DEPTH ROLL NEXT PG 25.2 }
  387.           35.2 { DROP 1 5 START DEPTH ROLLD NEXT PG 35.2 }
  388.         } +
  389.       END
  390.       DUP2 SWAP POS
  391.       IF DUP THEN
  392.         1 + GET EVAL
  393.       ELSE
  394.         DROP2
  395.       END
  396.     UNTIL
  397.       16.1 ==
  398.     END
  399.     CLEAR
  400.   ELSE
  401.     @ NOAPPTS
  402.     DO
  403.       @ NOHEAD
  404.       DSTR TIME TSTR 1 12 SUB "     " SWAP + "   NO APPTS YET FOR"
  405.       CLLCD 1 DISP 3 DISP
  406.       @ SETNO
  407.       { "" "" "" "ADD" "" "RTN" } MENU
  408.       -1 WAIT
  409.       @ DOK3
  410.       CASE
  411.         DUP 91.3 == THEN OFF END
  412.         DUP 14.1 == THEN DROP DSTR 8 "" 0 4 \->LIST BEG 16.1 END
  413.       END
  414.     UNTIL
  415.      16.1 ==
  416.     END
  417.   END
  418. \>>
  419.  
  420. PG
  421. @ called by APPTS (5)
  422. @ Put the (first 5) appointments on the stack in the display,
  423. @  and show the menu.
  424. \<<
  425.   @ MHEAD
  426.   DSTR TIME TSTR 1 12 SUB "     " SWAP + "Appts and meetings for"
  427.   CLLCD 1 DISP 2 DISP
  428.   @ SETU3
  429.   { "EDIT" "ACK" "DEL" "ADD" "VIEW" "RTN" } MENU
  430.   DEPTH 5 MIN
  431.   @ POSTX
  432.   \-> d \<<
  433.     1 d FOR i
  434.       DUP 1 GET i 2 + DISP DEPTH ROLL
  435.     1 STEP
  436.     1 d START
  437.       DEPTH ROLLD
  438.     NEXT
  439.     @ TSK1
  440.     LCD\-> DUP { # 0h # Fh } { # 87h # 17h } SUB NEG
  441.     { # 0h # Fh } SWAP REPL \->LCD
  442.   \>>
  443. \>>
  444.  
  445.  
  446. BEG
  447. @ called by DOKEY, APPTS
  448. @ ADD or EDIT key: edit a new or existing appointment.
  449. \<<
  450.   DO
  451.     @ RFSH
  452.     CLLCD 1
  453.     GETI "Date " SWAP + 1 DISP
  454.     GETI "Hour " SWAP + 2 DISP
  455.     GETI "Msg. " SWAP + 3 DISP
  456.     DROP "Press a softkey first" 5 DISP
  457.     @ SETU4
  458.     { "DATE" "TIME" "MSG" "RPT" "SET" "ABRT" } MENU
  459.     -1 WAIT
  460.     @ DOK4
  461.     { 91.3 OFF
  462.       11.1 { DROP DATTE 11.1 }
  463.       12.1 { DROP HOUR 12.1 }
  464.       13.1 { DROP MSSG 13.1 }
  465.       14.1 { REPEET 14.1 }
  466.       15.1 { DROP STOALARM DROP 1 SF 15.1 }
  467.       16.1 { 1 CF SWAP DROP }
  468.     }
  469.     DUP2 SWAP POS
  470.     IF DUP THEN
  471.       1 + GET EVAL
  472.     ELSE
  473.       DROP2 1000 .2 BEEP
  474.     END
  475.   UNTIL
  476.     DUP 15.1 == SWAP 16.1 == OR
  477.   END
  478. \>>
  479.  
  480. MSSG
  481. @ called by BEG
  482. @ MSG key: change text message for appointment.
  483. \<<
  484.   { } MENU 3 GETI SWAP DROP \Ga 2 \->LIST
  485.   "Message:\010Then press ENTER." SWAP INPUT 3 SWAP PUT
  486. \>>
  487.  
  488. HOUR
  489. @ called by BEG
  490. @ TIME key: change time for appointment.
  491. \<<
  492.   { } MENU 2 GETI SWAP DROP \->STR -1 2 \->LIST
  493.   "Hour (HH.MM):\010Then press ENTER." SWAP INPUT OBJ\-> 2 SWAP PUT
  494. \>>
  495.  
  496. DATTE
  497. @ called by BEG
  498. @ DATE key: change date for appointment.
  499. \<<
  500.   DO
  501.     { } MENU 1 GETI SWAP DROP \->STR -1 2 \->LIST 
  502.     "Date (MM.DDYYYY):\010Then press ENTER." SWAP INPUT OBJ\->
  503.   UNTIL
  504.     DUP DUP DUP IP DUP 0 > SWAP 13 < AND SWAP FP 100 * IP 32 < AND
  505.     SWAP 100 * FP 10000 * 1990 \>= AND DUP
  506.     IF NOT THEN
  507.       SWAP DROP CLLCD
  508.       "Bad date. The rules:\010\0100 < MM < 13\0100 < DD < 32\0101990 \<= YYYY\010\010Press a top row key"
  509.       1 DISP -1 WAIT DROP
  510.     END
  511.   END
  512.   1 SWAP PUT
  513. \>>
  514.  
  515. REPEET
  516. @ called by BEG
  517. @ RPT key: change repeat specification for appointment.
  518. @ (Note: this function expects no number to be entered if NONE will
  519. @  be pressed on the next menu.)
  520. \<<
  521.   { } MENU
  522.   "Repeat #. Then ENTER."  "" INPUT OBJ\->
  523.   { "Week" "Day" "Hour" "Min" "Sec" "None" } MENU
  524.   "Now press repeat unit" 3 DISP -1 WAIT
  525.   { 11.1 4954521600
  526.     12.1 707788800
  527.     13.1 29491200
  528.     14.1 491520
  529.     15.1 8192
  530.   }
  531.   DUP ROT POS
  532.   IF DUP THEN
  533.     1 + GET *
  534.   ELSE
  535.     DROP2 0                             @ this assumes no input
  536.   END
  537.   SWAP DROP 4 SWAP PUT
  538. \>>
  539.  
  540. RDOSCR
  541. @ called by YRMIN, YRPLS, MOMIN, MOPL
  542. @ Change current date and display the new month.
  543. \<<
  544.   SETUP2 MNTH LCD\-> RC HLIT2 DUP \->LCD SWAP
  545. \>>
  546.  
  547. HLIT2
  548. @ called by RDOSCR, PWEEK (2), NWEEK (2), DYMIN (2), DYPL (2)
  549. @ Toggle the highlighting of the current date in the calendar.
  550. \<<
  551.   COL R\->B ROW R\->B 2 \->LIST DUP2
  552.   COL 12 + R\->B ROW 8 + R\->B 2 \->LIST
  553.   SUB NEG REPL
  554. \>>
  555.  
  556. RC
  557. @ called by RDOSCR, PWEEK, NWEEK, DYMIN, DYPL
  558. @ Update ROW and COL for the current date in the calendar.
  559. \<<
  560.   Dy ADR + 7 / FP 126 * 1 - 'COL' STO
  561.   Dy ADR + 7 / IP 1 + 8 * 1 - 'ROW' STO
  562. \>>
  563.  
  564. SETUP2
  565. @ called by REFRESH, RDOSCR
  566. @ Set DSTR, update Mo, Dy, Yr, Day1, and ADR.
  567. \<<
  568.   DUP 'DSTR' STO DUP
  569.   @ MMYY
  570.   DUP IP 'Mo' STO
  571.   FP 100 * DUP IP 'Dy' STO
  572.   FP 10000 * \->STR 'Yr' STO
  573.   DUP
  574.   @ DFRST
  575.   DUP IP SWAP FP 100 * FP 1 + 100 / + TIME TSTR 1 3 SUB 'Day1' STO
  576.   @ CADR
  577.   { "SUN" "MON" "TUE" "WED" "THU" "FRI" "SAT" } Day1 POS 2 - 'ADR' STO
  578. \>>
  579.  
  580. MNTH
  581. @ called by REFRESH, RDOSCR
  582. @ Put the current month in the display.
  583. \<<
  584.   @ HEADR
  585.   { "January " "February " "March " "April " "May " "June "
  586.     "July " "August " "September " "October " "November " "December " }
  587.   Mo GET Yr + "  " SWAP + 1 DISP
  588.   DSTR LMNTH Day1
  589.   @ MN
  590.   \-> n d \<<
  591.   "                   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"
  592.   { "SAT" "FRI" "THU" "WED" "TUE" "MON" "SUN" } d POS 3 * 2 -
  593.   n 3 * 17 + SUB
  594.   2 7 FOR i
  595.     DUP i 2 - 21 * 1 + DUP 19 + SUB i DISP
  596.   NEXT
  597.   DROP
  598.   \>>
  599. \>>
  600.  
  601. LMNTH
  602. @ called by NWEEK, DYPL, MNTH
  603. @ Compute the number of days in the month.
  604. \<<
  605.   DUP IP SWAP 100 * FP 100 / .01 + + DUP 1 + DUP
  606.   IF 13 > THEN
  607.     FP 1.000001 +
  608.   END
  609.   DDAYS
  610. \>>
  611.  
  612.  
  613. SRCSTR ""                               @ used in CHKALRM, GETSTR
  614.  
  615. MYFLGS {  # 90400000FF0h # 0h  }        @ used by APPT (not in APDIR)
  616.  
  617. END @ APDIR
  618.  
  619.  
  620.